package at.codebase.web.util.json;

import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;


import at.codebase.core.FeedbackData;
import at.codebase.core.search.ItemSearchResult;
import at.codebase.core.search.ItemSearchResultInfo;
import at.codebase.db.entities.EItem;
import at.codebase.db.entities.EItemFeedback;
import at.codebase.db.entities.GeoPoint;
import at.codebase.db.entities.EItemFeedback.EItemFeedbackRating;

/**
 * @author Daniel Marth <danielmarth@gmx.at>
 */
public class JsonDecoder {

	public static GeoPoint decodeLocation(final JSONObject obj) {
		if (obj == null) {
			return new GeoPoint(0.0, 0.0);
		}
		return new GeoPoint(
				((Double) obj.get(JsonKeys.LATITUDE)).doubleValue(),
				((Double) obj.get(JsonKeys.LONGITUDE)).doubleValue());
	}

	public static GeoPoint decodeLocation(final String jsonString) {
		return decodeLocation((JSONObject) JSONValue.parse(jsonString));
	}

	public static EItem decodeItem(final JSONObject obj) {
		EItem item = new EItem();
		if (obj == null) {
			return item;
		}
		item.setId((Long) obj.get(JsonKeys.ITEM_ID));
		item.setTitle((String) obj.get(JsonKeys.TITLE));
		item.setDescription((String) obj.get(JsonKeys.DESCRIPTION));
		item.setActive(((Boolean) obj.get(JsonKeys.ACTIVE)).booleanValue());
		item.setDeleted(((Boolean) obj.get(JsonKeys.DELETED)).booleanValue());
		item.setPrice(((Double) obj.get(JsonKeys.PRICE)).doubleValue());
		item.setTimeCreate(((Long) obj.get(JsonKeys.TIME_CREATE)).longValue());
		item.setTimeExpiration(((Long) obj.get(JsonKeys.TIME_EXPIRATION))
				.longValue());
		if (obj.containsKey(JsonKeys.LOCATION)) {
			item.setLocation(decodeLocation((JSONObject) obj
					.get(JsonKeys.LOCATION)));
		} else {
			item.setLocation(null);
		}
		return item;
	}

	public static EItem decodeItem(final String jsonString) {
		return decodeItem((JSONObject) JSONValue.parse(jsonString));
	}

	public static List<EItem> deocdeItems(final JSONObject obj) {
		List<EItem> items = new ArrayList<EItem>();
		if (obj == null) {
			return items;
		}
		JSONArray array = (JSONArray) obj.get(JsonKeys.ITEM_LIST);
		for (Object jsonItem : array) {
			items.add(decodeItem((JSONObject) jsonItem));
		}
		return items;
	}

	public static List<EItem> deocdeItems(final String jsonString) {
		return deocdeItems((JSONObject) JSONValue.parse(jsonString));
	}

	public static ItemSearchResult decodeItemSearchResult(final JSONObject obj) {
		if (obj == null) {
			return new ItemSearchResult("", "");
		}
		String tSnippet = (String) obj.get(JsonKeys.TITLE_SNIPPET);
		String descSnippet = (String) obj.get(JsonKeys.DESCRIPTION_SNIPPET);
		ItemSearchResult result = new ItemSearchResult(tSnippet, descSnippet);
		result.setItem(decodeItem((JSONObject) obj.get(JsonKeys.ITEM)));
		return result;
	}

	public static ItemSearchResult decodeItemSearchResult(
			final String jsonString) {
		return decodeItemSearchResult((JSONObject) JSONValue.parse(jsonString));
	}

	public static List<ItemSearchResult> decodeSearchResults(
			final JSONObject obj) {
		List<ItemSearchResult> results = new ArrayList<ItemSearchResult>();
		if (obj == null) {
			return results;
		}
		JSONArray array = (JSONArray) obj.get(JsonKeys.ITEM_SEARCH_RESULT_LIST);
		for (Object jsonSearchResult : array) {
			results.add(decodeItemSearchResult((JSONObject) jsonSearchResult));
		}
		return results;
	}

	public static List<ItemSearchResult> decodeSearchResults(
			final String jsonString) {
		return decodeSearchResults((JSONObject) JSONValue.parse(jsonString));
	}

	public static ItemSearchResultInfo decodeItemSearchResultInfo(
			final JSONObject obj) {
		if (obj == null) {
			return new ItemSearchResultInfo(0,
					new ArrayList<ItemSearchResult>(), new ArrayList<EItem>());
		}
		List<ItemSearchResult> results = decodeSearchResults((JSONObject) obj
				.get(JsonKeys.ITEM_SEARCH_RESULT_LIST));
		List<EItem> items = deocdeItems((JSONObject) obj
				.get(JsonKeys.ITEM_LIST));
		ItemSearchResultInfo resultInfo = new ItemSearchResultInfo(
				((Long) obj.get(JsonKeys.COUNT)).longValue(), results, items);
		return resultInfo;
	}

	public static ItemSearchResultInfo decodeItemSearchResultInfo(
			final String jsonString) {
		return decodeItemSearchResultInfo((JSONObject) JSONValue
				.parse(jsonString));
	}

	public static FeedbackData decodeFeedbacks(final JSONObject obj) {
		FeedbackData data = new FeedbackData();
		if (obj == null) {
			return data;
		}		
		data.setUserAlreadyRated(((Boolean) obj.get(JsonKeys.ALREADY_RATED))
				.booleanValue());
		data.setRatingAverage(((Double) obj.get(JsonKeys.RATING)).doubleValue());
		data.setItemFeedbackList(decodeFeedbackList((JSONObject) obj
				.get(JsonKeys.FEEDBACK_LIST)));
		return data;
	}

	public static FeedbackData decodeFeedbacks(final String jsonString) {
		return decodeFeedbacks((JSONObject) JSONValue.parse(jsonString));
	}

	private static List<EItemFeedback> decodeFeedbackList(final JSONObject obj) {
		List<EItemFeedback> results = new ArrayList<EItemFeedback>();
		if (obj == null) {
			return results;
		}
		JSONArray array = (JSONArray) obj.get(JsonKeys.FEEDBACK_LIST);
		for (Object jsonFeedback : array) {
			results.add(decodeFeedback((JSONObject) jsonFeedback));
		}
		return results;
	}

	public static List<EItemFeedback> decodeFeedbackList(final String jsonString) {
		return decodeFeedbackList((JSONObject) JSONValue.parse(jsonString));
	}

	private static EItemFeedback decodeFeedback(final JSONObject obj) {
		EItemFeedback feedback = new EItemFeedback();
		if (obj == null) {
			return feedback;
		}
		feedback.setId((Long) obj.get(JsonKeys.FEEDBACK_ID));
		feedback.setFeedbackContent((String) obj.get(JsonKeys.FEEDBACK_CONTENT));
		feedback.setTimeCreate(((Long) obj.get(JsonKeys.TIME_CREATE))
				.longValue());
		feedback.setAuthor(((Long) obj.get(JsonKeys.USER_ID)).longValue());
		switch (((Integer) obj.get(JsonKeys.RATING)).intValue()) {
		case 0:
			feedback.setFeedbackRating(EItemFeedbackRating.NO_RATING);
			break;
		case 1:
			feedback.setFeedbackRating(EItemFeedbackRating.RUBY_1);
			break;
		case 2:
			feedback.setFeedbackRating(EItemFeedbackRating.RUBY_2);
			break;
		case 3:
			feedback.setFeedbackRating(EItemFeedbackRating.RUBY_3);
			break;
		case 4:
			feedback.setFeedbackRating(EItemFeedbackRating.RUBY_4);
			break;
		case 5:
			feedback.setFeedbackRating(EItemFeedbackRating.RUBY_5);
			break;
		}
		return feedback;
	}

	public static EItemFeedback decodeFeedback(final String jsonString) {
		return decodeFeedback((JSONObject) JSONValue.parse(jsonString));
	}
	
	@SuppressWarnings("unchecked")
	public static List<Long> decodeIds(final JSONObject obj) {
		if(obj == null) {
			return new ArrayList<Long>();
		}
		return (List<Long>) obj.get(JsonKeys.ID_LIST);
	}
	
	public static List<Long> decodeIds(final String jsonString) {
		return decodeIds((JSONObject) JSONValue.parse(jsonString));
	}

}
